﻿#region License statement
// NJamb, a specification and delta-specification DSL
// Copyright (c) 2010-2011, Mark Knell
// Published under the MIT License; all other rights reserved
#endregion

#region using...
using System;
using System.Linq.Expressions;
using NJamb.NUnit;
using NJamb.Parser.SubjectBuilders;
using NJamb.Specifications.Delta;
using NUnit.Framework;
using Stile.Patterns.SelfDescribingPredicates;
using Stile.Testing.SampleTypes;
using Stile.Types.Expressions;
#endregion

namespace NJamb.Tests.Specifications
{
	[TestFixture]
	public class NotifyPropertyChangedAcceptanceTests : EvaluatingSampleFixture
	{
		private NotifyingSample _notifyingSample;
		private Expression<Func<NotifyingSample, int>> _propertyExpectedToChange;
		private IRaisePropertyChangedDeltaSpecification<NotifyingSample> _testSubject;

		[SetUp]
		public void Init()
		{
			_notifyingSample = new NotifyingSample();
			_propertyExpectedToChange = x => x.Int;
			_testSubject = Specify.For(() => _notifyingSample).ThatItWillRaiseAPropertyChangedEventFor(_propertyExpectedToChange);
		}

		[Test]
		public void ThatItWillRaiseAPropertyChangedEventFor()
		{
			// arrange
			using(IPreconditionEvaluation preconditionEvaluation = _testSubject.EvaluatePrecondition())
			{
				_notifyingSample.Frob(_propertyExpectedToChange);
				Assert.That(preconditionEvaluation.Evaluation.Success, Is.True, "precondition");

				// act
				IEvaluation evaluation = preconditionEvaluation.GetPostcondition().Evaluate();

				// assert
				Assert.That(evaluation.Success, Is.True);
			}
		}

		[Test]
		public void ThatItWillRaiseAPropertyChangedEventFor_Fail()
		{
			// arrange
			Expression<Func<NotifyingSample, bool>> expression = x => x.Bool;
			Assert.That(expression.GetPropertyInfo(), Is.Not.EqualTo(_propertyExpectedToChange.GetPropertyInfo()), "precondition");

			// act
			IPreconditionEvaluation preconditionEvaluation;
			using (preconditionEvaluation = _testSubject.EvaluatePrecondition())
			{
				_notifyingSample.Frob(expression);

				// assert
				using (IEvaluable<IEvaluation> postcondition = preconditionEvaluation.GetPostcondition())
				{
					AssertEvaluationFailed(postcondition.Evaluate(),
						"expected _notifyingSample would notify of a change to its property Int",
						" but it notified of a change to Bool instead.");
				}
			}
		}

		[Test]
		public void ThatItWillRaiseAPropertyChangedEventFor_NotRaised()
		{
			// no action, just assert
			AssertEvaluationFailed(_testSubject.EvaluatePrecondition().GetPostcondition().Evaluate(),
				"expected _notifyingSample would notify of a change to its property Int",
				" but it did not raise INotifyPropertyChanged at all.");
		}
	}
}
